package de.juergenschmied.prefsImpl;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.prefs.AbstractPreferences;
import java.util.prefs.BackingStoreException;

import org.apache.log4j.Logger;

public class PreferencesImpl extends AbstractPreferences {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(PreferencesImpl.class);
	private int myPK;

	protected PreferencesImpl() {
		super(null, "");

		try {
			logger.debug("PreferencesImpl()");
			JDBCBackend backend = JDBCBackend.getInstance();
			myPK = backend.getChildNodePK(1, "rootNode");

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public PreferencesImpl(AbstractPreferences parent, String name, int childPK) {
		super(parent, name);
		myPK = childPK;
	}

	@Override
	protected AbstractPreferences childSpi(String name) {
		logger.debug("childSpi(String) - name = " + name);
		try {
			JDBCBackend backend = JDBCBackend.getInstance();

			int childPK = backend.getChildNodePK(myPK, name);
			if (childPK == -1) {
				logger.debug("create new Node name=" + name);
				childPK = backend.insertNode(myPK, name);
			} else {
				logger.debug("found existing Node " + childPK);
			}
			return new PreferencesImpl(this, name, childPK);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	protected String[] childrenNamesSpi() throws BackingStoreException {
		logger.debug("childrenNamesSpi() myPK = " + myPK);

		try {
			String[] result = JDBCBackend.getInstance().getChildren(myPK);
			logger.debug("  childrenNamesSpi() childs = " + Arrays.toString(result));
			return result;
		} catch (SQLException e) {
			throw new BackingStoreException(e);
		}
	}

	@Override
	protected String getSpi(String key) {
		logger.debug("getSpi(String) - key=" + key);
		try {
			String value = JDBCBackend.getInstance().getKey(myPK, key);

			logger.debug("  getSpi(String) - value=" + value);
			return value;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	protected String[] keysSpi() throws BackingStoreException {
		logger.debug("keysSpi()");

		try {
			String[] keys = JDBCBackend.getInstance().getKeys(myPK);
			logger.debug("  keysSpi() keys = " + Arrays.toString(keys));
			return keys;
		} catch (SQLException e) {
			throw new BackingStoreException(e);
		}
	}

	@Override
	protected void putSpi(String key, String value) {
		logger.debug("putSpi(String, String) - key=" + key + ", value=" + value);
		try {
			JDBCBackend instance = JDBCBackend.getInstance();
			instance.removeValue(myPK, key);
			instance.insertValue(myPK, key, value);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

	}

	@Override
	protected void removeNodeSpi() throws BackingStoreException {
		logger.debug("removeNodeSpi() pk = " + myPK);

		try {
			JDBCBackend instance = JDBCBackend.getInstance();
			instance.removeNode(myPK);
		} catch (SQLException e) {
			throw new BackingStoreException(e);
		}
	}

	@Override
	protected void removeSpi(String key) {
		logger.debug("removeSpi(String) - key = " + key);

		try {
			JDBCBackend.getInstance().removeValue(myPK, key);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	protected void syncSpi() throws BackingStoreException {
		logger.debug("syncSpi()");
		try {
			JDBCBackend.getInstance().sync();
		} catch (SQLException e) {
			throw new BackingStoreException(e);
		}
	}

	@Override
	protected void flushSpi() throws BackingStoreException {
		logger.debug("flushSpi()");
		try {
			JDBCBackend.getInstance().flush();
		} catch (SQLException e) {
			throw new BackingStoreException(e);
		}
	}
}
